/*
 * jxSwing Project (2014)
 * 
 * by Denilson Edinaldo Pinto
 * 
 * LGPL
 * Copyright (C) 2014
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.jxSwing.component.bar;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.print.PrinterException;
import java.text.MessageFormat;
import java.util.Locale;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.JobName;
import javax.swing.Box;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTable.PrintMode;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;

import org.jxSwing.component.button.AddButton;
import org.jxSwing.component.button.AutoResizeColumnsButton;
import org.jxSwing.component.button.ClearButton;
import org.jxSwing.component.button.EditButton;
import org.jxSwing.component.button.ExportButton;
import org.jxSwing.component.button.FindButton;
import org.jxSwing.component.button.PrintButton;
import org.jxSwing.component.button.RemoveButton;
import org.jxSwing.component.dialog.TableExportDialog;
import org.jxSwing.component.dialog.TableFilterDialog;
import org.jxSwing.component.panel.BeanTablePanel;
import org.jxSwing.i18n.I18N;
import org.jxUtils.check.CheckUtil;
import org.jxUtils.lang.StringUtil;

/**
 * @author Denilson Edinaldo Pinto
 * @porject jxSwing
 * @package org.jxSwing.component.bar
 * @date 22/03/2014 - 17:09:45
 * @param <Bean>
 */
public final class HeaderTableBar<Bean> extends JToolBar {
	
	private static final long serialVersionUID = 893366585671098271L;
	
	private ActionListener actionAdd = new ActionAdd();
	
	private ActionListener actionEdit = new ActionEdit();
	
	private ActionListener actionExport = new ActionExport();
	
	private ActionListener actionFind = new ActionFind();
	
	private ActionListener actionPrint = new ActionPrint();
	
	private ActionListener actionRemove = new ActionRemove();
	
	private AddButton btnAdd;
	
	private EditButton btnEdit;
	
	private RemoveButton btnRemove;
	
	private Component hg1;
	
	private JLabel lblTitulo;
	
	private ExportButton btnExport;
	
	private FindButton btnFilter;
	
	private ClearButton btnClearFilter;
	
	private PrintButton btnPrint;
	
	private Component hs1;
	
	private AutoResizeColumnsButton btnAutoResizeColumns;
	
	private Component hg2;
	
	private final BeanTablePanel<Bean> tablePanel;
	
	private int rowToEdit = -1;
	
	private Component hs2;
	
	/**
	 * @param pnlBeanTable
	 */
	public HeaderTableBar(final BeanTablePanel<Bean> pnlBeanTable) {
	
		this.tablePanel = pnlBeanTable;
		
		initGUI();
	}
	
	/**
	 * @param event
	 */
	private void editAction(KeyEvent event) {
	
		final int selectedRow = getTablePanel().getSelectedRow();
		final int selectedColumn = getTablePanel().getSelectedColumn();
		
		// 
		if(selectedRow != rowToEdit && rowToEdit >= 0) {
			
			getTablePanel().setRowEditable(rowToEdit, false);
			
			rowToEdit = -1;
			
			setEnabledCrudButtons(true);
			getBtnRemove().setEnabled(true);
			
		}else if(isVisibleEdit()) {
			
			setEnabledCrudButtons(true);
			getBtnRemove().setEnabled(true);
			
			//
			if(rowToEdit >= 0) {
				
				getTablePanel().setRowEditable(rowToEdit, true);
				
				getBtnAdd().setEnabled(false);
				getBtnEdit().setEnabled(false);
				getBtnRemove().setEnabled(false);
				
				// 
				if(event != null) {
					
					getTablePanel().getCellEditor(rowToEdit, selectedColumn).isCellEditable(event);
				}
			}
			
		}else if(isVisibleRemove()) {
			
			getBtnRemove().setEnabled(true);
		}
	}
	
	/**
	 * @return the hg1
	 */
	private Component getHg1() {
	
		if(hg1 == null) {
			hg1 = Box.createHorizontalGlue();
		}
		return hg1;
	}
	
	/**
	 * @return the hg2
	 */
	private Component getHg2() {
	
		if(hg2 == null) {
			hg2 = Box.createHorizontalGlue();
		}
		return hg2;
	}
	
	/**
	 * @return the hs1
	 */
	private Component getHs1() {
	
		if(hs1 == null) {
			hs1 = Box.createHorizontalStrut(5);
		}
		return hs1;
	}
	
	/**
	 * 
	 */
	private void initGUI() {
	
		//
		setFloatable(false);
		add(getHg1());
		add(getLblTitulo());
		add(getHg2());
		add(getBtnAdd());
		add(getBtnEdit());
		add(getBtnRemove());
		add(getHs1());
		add(getBtnExport());
		add(getBtnFilter());
		add(getBtnClearFilter());
		add(getBtnPrint());
		add(getHs2());
		add(getBtnAutoResizeColumns());
		
		//
		getTablePanel().getTable().addMouseListener(new MouseAdapter() {
			
			@Override
			public void mouseClicked(final MouseEvent mouseEvent) {
			
				editAction(null);
			}
		});
	}

	/**
	 * @return the btnAdd
	 */
	public AddButton getBtnAdd() {
	
		if(btnAdd == null) {
			btnAdd = new AddButton();
			btnAdd.addActionListener(actionAdd);
		}
		return btnAdd;
	}
	
	/**
	 * @return the btnAutoResizeColumns
	 */
	public AutoResizeColumnsButton getBtnAutoResizeColumns() {
	
		if(btnAutoResizeColumns == null) {
			
			final boolean autoResizeColumns = getTablePanel().getAutoResizeMode() == JTable.AUTO_RESIZE_OFF;
			
			btnAutoResizeColumns = new AutoResizeColumnsButton(autoResizeColumns) {
				
				private static final long serialVersionUID = -826518298184562050L;
				
				@Override
				public void action(final boolean autoResizeColumns) {
				
					getTablePanel().autoResizeColumns(autoResizeColumns);
				}
			};
			btnAutoResizeColumns.setSize(new Dimension(40, 25));
		}
		return btnAutoResizeColumns;
	}
	
	/**
	 * @return the btnClearFilter
	 */
	public ClearButton getBtnClearFilter() {
	
		if(btnClearFilter == null) {
			btnClearFilter = new ClearButton();
			btnClearFilter.setVisible(false);
			btnClearFilter.addActionListener(new ActionListener() {
				
				@Override
				public void actionPerformed(final ActionEvent actionEvent) {
				
					getTablePanel().clearFilter();
				}
			});
		}
		return btnClearFilter;
	}
	
	/**
	 * @return the btnEdit
	 */
	public EditButton getBtnEdit() {
	
		if(btnEdit == null) {
			btnEdit = new EditButton();
			btnEdit.setEnabled(false);
			btnEdit.addActionListener(actionEdit);
		}
		return btnEdit;
	}
	
	/**
	 * @return the btnExport
	 */
	public ExportButton getBtnExport() {
	
		if(btnExport == null) {
			btnExport = new ExportButton();
			btnExport.addActionListener(actionExport);
		}
		return btnExport;
	}
	
	/**
	 * @return the btnFilter
	 */
	public FindButton getBtnFilter() {
	
		if(btnFilter == null) {
			btnFilter = new FindButton();
			btnFilter.addActionListener(actionFind);
		}
		return btnFilter;
	}
	
	/**
	 * @return the btnPrint
	 */
	public PrintButton getBtnPrint() {
	
		if(btnPrint == null) {
			btnPrint = new PrintButton();
			btnPrint.addActionListener(actionPrint);
		}
		return btnPrint;
	}
	
	/**
	 * @return the btnRemove
	 */
	public RemoveButton getBtnRemove() {
	
		if(btnRemove == null) {
			btnRemove = new RemoveButton();
			btnRemove.setEnabled(false);
			btnRemove.addActionListener(actionRemove);
		}
		return btnRemove;
	}
	
	/**
	 * @return the hs2
	 */
	public Component getHs2() {
	
		if(hs2 == null) {
			hs2 = Box.createHorizontalStrut(5);
		}
		return hs2;
	}
	
	/**
	 * @return the lblTitulo
	 */
	public JLabel getLblTitulo() {
	
		if(lblTitulo == null) {
			lblTitulo = new JLabel();
			lblTitulo.setFont(new Font(lblTitulo.getFont().getName(), Font.BOLD, lblTitulo.getFont().getSize()));
			lblTitulo.setHorizontalAlignment(SwingConstants.CENTER);
			lblTitulo.setHorizontalTextPosition(SwingConstants.CENTER);
		}
		return lblTitulo;
	}
	
	/**
	 * @return the tablePanel
	 */
	public BeanTablePanel<Bean> getTablePanel() {
	
		return tablePanel;
	}
	
	/**
	 * @return the title
	 */
	public String getTitle() {
	
		return getLblTitulo().getText();
	}
	
	/**
	 * @return Add Button is Enabled
	 */
	public boolean isEnabledAdd() {
	
		return getBtnAdd().isEnabled();
	}
	
	/**
	 * @return AutoResizeColumns Button is Enabled
	 */
	public boolean isEnabledAutoResizeColumns() {
	
		return getBtnAutoResizeColumns().isEnabled();
	}
	
	/**
	 * @return Export Button is Enabled
	 */
	public boolean isEnabledExport() {
	
		return getBtnExport().isEnabled();
	}
	
	/**
	 * @return Filter Button is Enabled
	 */
	public boolean isEnabledFilter() {
	
		return getBtnFilter().isEnabled();
	}
	
	/**
	 * @return Print Button is Enabled
	 */
	public boolean isEnabledPrint() {
	
		return getBtnPrint().isEnabled();
	}
	
	/**
	 * @return true if Add Button is visible
	 */
	public boolean isVisibleAdd() {
	
		return getBtnAdd().isVisible();
	}
	
	/**
	 * @return true if Edit Button is visible
	 */
	public boolean isVisibleEdit() {
	
		return getBtnEdit().isVisible();
	}
	
	/**
	 * @return true if Remove Button is visible
	 */
	public boolean isVisibleRemove() {
	
		return getBtnRemove().isVisible();
	}
	
	/**
	 * @param actionAdd
	 */
	public void setActionAdd(ActionListener actionAdd) {
		
		getBtnAdd().removeActionListener(this.actionAdd);
		
		this.actionAdd = actionAdd;
		
		getBtnAdd().addActionListener(this.actionAdd);
	}
	
	/**
	 * @param actionEdit
	 */
	public void setActionEdit(ActionListener actionEdit) {
		
		getBtnEdit().removeActionListener(this.actionEdit);
		
		this.actionEdit = actionEdit;
		
		getBtnEdit().addActionListener(this.actionEdit);
	}
	
	/**
	 * @param actionExport
	 */
	public void setActionExport(ActionListener actionExport) {
		
		getBtnExport().removeActionListener(this.actionExport);
		
		this.actionExport = actionExport;
		
		getBtnExport().addActionListener(this.actionExport);
	}
	
	/**
	 * @param actionFind
	 */
	public void setActionFind(ActionListener actionFind) {
		
		getBtnFilter().removeActionListener(this.actionFind);
		
		this.actionFind = actionFind;
		
		getBtnFilter().addActionListener(this.actionFind);
	}
	
	/**
	 * @param actionPrint
	 */
	public void setActionPrint(ActionListener actionPrint) {
		
		getBtnPrint().removeActionListener(this.actionPrint);
		
		this.actionPrint = actionPrint;
		
		getBtnPrint().addActionListener(this.actionPrint);
	}
	
	/**
	 * @param actionRemove
	 */
	public void setActionRemove(ActionListener actionRemove) {
		
		getBtnRemove().removeActionListener(this.actionRemove);
		
		this.actionRemove = actionRemove;
		
		getBtnRemove().addActionListener(this.actionRemove);
	}
	
	/**
	 * @param value
	 */
	public void setAutoResizeColumns(final boolean value) {
	
		getBtnAutoResizeColumns().setSelected(value);
		getTablePanel().autoResizeColumns( !value);
	}
	
	/**
	 * @return autoResizeColumns
	 */
	public boolean getAutoResizeColumns() {
	
		return getBtnAutoResizeColumns().isSelected();
	}
	
	/**
	 * @param enabled
	 */
	public void setEnabledAutoResizeColumns(final boolean enabled) {
	
		//
		if(enabled) {
			
			getBtnAutoResizeColumns().setVisible(true);
		}
		
		getBtnAutoResizeColumns().setEnabled(enabled);
	}
	
	/**
	 * @param enabled
	 */
	public void setEnabledClearFilter(final boolean enabled) {
	
		//
		if(enabled) {
			
			getBtnClearFilter().setVisible(true);
		}
		
		getBtnClearFilter().setEnabled(enabled);
	}
	
	/**
	 * @param enabled
	 */
	public void setEnabledCrudButtons(final boolean enabled) {
	
		getBtnAdd().setEnabled(enabled);
		getBtnRemove().setEnabled(false);
		
		// 
		if(enabled && isVisibleEdit()) {
			
			getTablePanel().locked();
			getBtnEdit().setEnabled(true);
		}
	}
	
	/**
	 * @param enabled
	 */
	public void setEnabledExport(final boolean enabled) {
	
		//
		if(enabled) {
			
			getBtnExport().setVisible(true);
		}
		
		getBtnExport().setEnabled(enabled);
	}
	
	/**
	 * @param enabled
	 */
	public void setEnabledFilter(final boolean enabled) {
	
		//
		if(enabled) {
			
			getBtnFilter().setVisible(true);
		}
		
		getBtnFilter().setEnabled(enabled);
	}
	
	/**
	 * @param enabled
	 */
	public void setEnabledPrint(final boolean enabled) {
	
		//
		if(enabled) {
			
			getBtnPrint().setVisible(true);
		}
		
		getBtnPrint().setEnabled(enabled);
	}
	
	/**
	 * @param enabled
	 */
	public void setEnabledTools(final boolean enabled) {
	
		setEnabledCrudButtons(enabled);
		setEnabledExport(enabled);
		setEnabledFilter(enabled);
		setEnabledPrint(enabled);
		setEnabledAutoResizeColumns(enabled);
	}
	
	/**
	 * @param tableTitle
	 */
	public void setTitle(final String tableTitle) {
	
		getLblTitulo().setText(tableTitle != null ? tableTitle.trim() : "");
	}
	
	/**
	 * @param visible
	 */
	public void setVisibleAutoResizeColumns(final boolean visible) {
	
		getHs1().setVisible(visible);
		getBtnAutoResizeColumns().setVisible(visible);
	}
	
	/**
	 * @param visible
	 */
	public void setVisibleClearFilter(final boolean visible) {
	
		getBtnClearFilter().setVisible(visible);
		getHs1().setVisible(visible);
	}
	
	/**
	 * @param visible
	 */
	public void setVisibleCrudButtons(final boolean visible) {
		
		setVisibleCrudButtons(visible, visible, visible);
	}
	
	/**
	 * @param visibleAdd
	 * @param visibleEdit
	 * @param visibleRemove
	 */
	public void setVisibleCrudButtons(final boolean visibleAdd, final boolean visibleEdit, final boolean visibleRemove) {
	
		getBtnAdd().setVisible(visibleAdd);
		getBtnEdit().setVisible(visibleEdit);
		getBtnRemove().setVisible(visibleRemove);
		
		//
		if(visibleEdit && getBtnEdit().isEnabled()) {
			
			getTablePanel().locked();
		}
	}
	
	/**
	 * @param visible
	 */
	public void setVisibleExport(final boolean visible) {
	
		getBtnExport().setVisible(visible);
		getHs1().setVisible(visible);
	}
	
	/**
	 * @param visible
	 */
	public void setVisibleFilter(final boolean visible) {
	
		getBtnFilter().setVisible(visible);
		getHs1().setVisible(visible);
	}
	
	/**
	 * @param visible
	 */
	public void setVisiblePrint(final boolean visible) {
	
		getBtnPrint().setVisible(visible);
		getHs1().setVisible(visible);
	}
	
	/**
	 * @param visible
	 */
	public void setVisibleTools(final boolean visible) {
	
		setVisibleCrudButtons(visible, visible, visible);
		getBtnExport().setVisible(visible);
		getBtnFilter().setVisible(visible);
		getBtnPrint().setVisible(visible);
		getHs1().setVisible(visible);
		getBtnAutoResizeColumns().setVisible(visible);
	}
	
	/**
	 * @author Denilson Edinaldo Pinto
	 * @porject jxSwing
	 * @package org.jxSwing.component.bar
	 * @date 24/12/2014 - 21:59:39
	 */
	private class ActionAdd implements ActionListener {
		
		@Override
		public void actionPerformed(final ActionEvent actionEvent) {
		
			getTablePanel().addRow();
			getTablePanel().setRowEditable(getTablePanel().getLastRowIndex(), true);
		}
	}
	
	/**
	 * @author Denilson Edinaldo Pinto
	 * @porject jxSwing
	 * @package org.jxSwing.component.bar
	 * @date 24/12/2014 - 22:03:16
	 */
	private class ActionEdit implements ActionListener {
		
		@Override
		public void actionPerformed(final ActionEvent actionEvent) {
		
			rowToEdit = getTablePanel().getSelectedRow();
			
			getTablePanel().setRowEditable(rowToEdit, true);
			
			getBtnEdit().setEnabled(false);
		}
	}
	
	/**
	 * @author Denilson Edinaldo Pinto
	 * @porject jxSwing
	 * @package org.jxSwing.component.bar
	 * @date 24/12/2014 - 22:03:42
	 */
	private class ActionExport implements ActionListener {
		
		@Override
		public void actionPerformed(final ActionEvent actionEvent) {
		
			new TableExportDialog(null, getTablePanel());
		}
	}
	
	/**
	 * @author Denilson Edinaldo Pinto
	 * @porject jxSwing
	 * @package org.jxSwing.component.bar
	 * @date 24/12/2014 - 22:04:09
	 */
	private class ActionFind implements ActionListener {
		
		@Override
		public void actionPerformed(final ActionEvent actionEvent) {
		
			new TableFilterDialog<Bean>(null, getTablePanel());
		}
	}
	
	/**
	 * @author Denilson Edinaldo Pinto
	 * @porject jxSwing
	 * @package org.jxSwing.component.bar
	 * @date 24/12/2014 - 22:04:33
	 */
	private class ActionPrint implements ActionListener {
		
		@Override
		public void actionPerformed(final ActionEvent actionEvent) {
		
			try {
				//
				String title = "";
				
				//
				if(CheckUtil.isNullOrAbsoluteEmpty(getTitle())) {
					
					final int option = JOptionPane.showConfirmDialog(getTablePanel().getParent(), I18N.component().wantToEnterTitle());
					
					//
					if(option == JOptionPane.YES_OPTION) {
						
						title = JOptionPane.showInputDialog(I18N.component().tableTitle() + ":");
					}
					
				}else {
					
					title = getTitle().trim();
				}
				
				//
				title = title != null && !title.trim().isEmpty() ? title.trim().toUpperCase() : getTablePanel().getTitle();
				
				MessageFormat header = null;
				final MessageFormat footer = new MessageFormat(I18N.component().records() + ": " + getTablePanel().getRowCount());
				
				PrintRequestAttributeSet attr = null;
				
				//
				if(title != null) {
					
					header = new MessageFormat(title);
					
					attr = new HashPrintRequestAttributeSet();
					attr.add(new JobName(StringUtil.normalize(title), Locale.getDefault()));
				}
				
				final boolean showDialogs = !GraphicsEnvironment.isHeadless();
				
				//
				getTablePanel().print(PrintMode.FIT_WIDTH, header, footer, showDialogs, attr, showDialogs);
				
			}catch(final PrinterException printerException) {
				
				printerException.printStackTrace();
			}
		}
	}
	
	/**
	 * @author Denilson Edinaldo Pinto
	 * @porject jxSwing
	 * @package org.jxSwing.component.bar
	 * @date 24/12/2014 - 22:04:55
	 */
	private class ActionRemove implements ActionListener {
		
		@Override
		public void actionPerformed(final ActionEvent actionEvent) {
		
			//
			if(JOptionPane.showConfirmDialog(null, I18N.component().reallyDeleteThisRecord()) == JOptionPane.YES_OPTION) {
				
				getTablePanel().removeSelectedRows();
			}
		}
	}
}
